GitHub Actions のSphinxビルド高速化
10ファル程度であれば影響は小さいですが、ファイル数が2桁~4桁あると全ビルドに数分~数十分かかってしまいます。
Sphinx-users.jp の例
https://gyazo.com/7f0c207f973578d73dbe5d7a25724270
www.freia.jp の例
遅い原因と対策案
build結果がCIごとに失われる
build結果をキャッシュする
キャッシュはブランチ別で持つと良さそう
特定の条件でキャッシュを破棄したらよさそう
1日以上経過?
ソースのタイムスタンプがチェックアウト時刻になってしまう
コミット時刻に修正する
インストールしたthemeのテンプレートが全ビルドの原因になる
pip install結果をキャッシュ するとよさそう
修正前
ソース
構成
ジョブを build と release の2ステップに分けていた
pipインストールやドキュメントビルド時の中間生成物をキャッシュしていない
Sphinxの3rd partyテーマをパッケージインストール
時間がかかっている箇所
1. ステップ間で生成物を渡すためのartifact処理(Upload 48秒/Download 22秒)
2. pip install (20秒)
3. sphinx-build で毎回フルビルド (30秒)
4. jakejarvis/s3-sync-action を使うための docker build (25秒)
5. S3への全ファイルがアップロード (30秒)
修正後
ソース
構成
ジョブを1ステップにした
pipのインストール先とビルド生成物をキャッシュした(1日、1ヶ月など期限は付けた)
Sphinxの3rd partyテーマをベンダリング
GitHubチェックアウト後にタイムスタンプをコミット時間に変更し差分ビルドした
S3アップロードを jakejarvis/s3-sync-action に頼らず時前でawscli v2をインストール 結果
1. artifact処理をなくした(Upload 48秒/Download 22秒) -> 0秒
2. pip installに時間がかかっている(20秒) -> キャッシュ利用 3秒
3. sphinx-build で毎回フルビルドが発生している(30秒) -> 1秒~差分による
4. jakejarvis/s3-sync-action を使うとdocker buildに時間がかかる(25秒) -> awscli v2 セットアップ 4秒
5. S3に全ファイルがアップロードされている(30秒) -> 差分のみになるはず
修正のポイント
ジョブのステップを分けると成果物の引き渡しのためのartifact処理に時間がかかる
対策: ステップを1つにまとめた
ステップを分けるのはキレイだけど、キレイより速さを選びました
pip install が毎回実行されていた
対策: ~/.cache/pip (wheel cache) と ~/.local/ (インストール先) をキャッシュ
キャッシュキーとして、OS名、 requirements.txtのhash値、年月(yyyymm)を使用
つまり、月に1回は最新パッケージに入れ替わるためフルインストールされるようにした
sphinx-buildの中間生成物が失われ、sphinx全ビルドされていた
対策: sphinxの build ディレクトリをブランチ別、1日以内でキャッシュする
キャッシュキーとして、OS名、 ブランチ名、年月日(yyyymmdd)を使用
ソースのタイムスタンプがチェックアウト時刻になりsphinx全ビルド
対策: タイムスタンプをコミット時刻に修正
pip install git+https://.. (ref) で3rd Partyテーマをインストールしたら、同バージョンがインストール済みでも毎回インストールされ、テンプレートのタイムスタンプが更新され、sphinx全ビルド 対策: PyPIからインストールする
ただし、リポジトリの最新版を使えない問題があったため、廃案
Sphinxの3rd partyテーマをパッケージインストールしたため、テンプレートファイルが更新されsphinx全ビルド
対策: テーマをベンダリングし、タイムスタンプ問題を回避
jakejarvis/s3-sync-action を使うとdocker buildに時間がかかる
仮にビルド済みイメージをpullできても、それがキャッシュされないと時間がかかるだろう
参考